package me.tuyou.mybatis.test.interfaces.plugin;

import lombok.extern.log4j.Log4j;
import me.tuyou.mybatis.test.interfaces.vo.Page;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.sql.Connection;
import java.sql.PreparedStatement;

@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
@Log4j
public class PagePlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //获取目标对象
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        //获取元数据
        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
        //获取绑定的sql
        BoundSql boundSql = (BoundSql) metaObject.getValue("boundSql");
        //获取参数对象
        Object parameterObject = boundSql.getParameterObject();
        //获取传入分页参数
        String sql = (String) metaObject.getValue("boundSql.sql");
        boolean isSelect = sql.trim().toLowerCase().startsWith("select");
        //如果不是查询语句，则直接进入下一个操作
        if (!isSelect || !(parameterObject instanceof Page)) {
            return invocation.proceed();
        }
        System.out.println("原来的sql：" + sql);
        //修改sql
        String page_sql = sql + " limit ?,?";
        //设置修改过的sql
        metaObject.setValue("boundSql.sql", page_sql);
        //如果没有传入相应的分页参数，则设置为默认值
        //获取参数
        PreparedStatement ps = (PreparedStatement) invocation.proceed();
        // 获取sql的总参数个数
        int paramCount = ps.getParameterMetaData().getParameterCount();
        // 设置分页参数
        Page page = (Page) parameterObject;
        ps.setInt(paramCount - 1, page.getOffset());
        ps.setInt(paramCount, page.getLimit());

        return ps;
    }
}
